/*
 *  TimeController.cpp
 *  SoundController0002
 *
 *  Created by ; on 10/09/05.
 *  Copyright 2010 jiro music. All rights reserved.
 *
 */

#include "TimeController.h"

namespace sc
{
	TimeController::TimeController( double beatsPerMiniute, double beatNumerator, double beatFraction )
		: beatsPerMinute( beatsPerMiniute ),
		  beatNumerator( beatNumerator ), 
		  beatFraction( beatFraction )
	{}

	void TimeController::SetTempo( double beatsPerMiniute_ )
	{
		beatsPerMinute = beatsPerMiniute_;
	}

	double TimeController::GetSecondsPerBar() const
	{
		return beatNumerator * GetSecondsPerBeat();
	}

	double TimeController::GetSecondsToBarCount( int barCount ) const
	{
		return barCount * GetSecondsPerBar();
	}

	double TimeController::GetSecondsPerBeat() const
	{
		return SecondsPerMinute / beatsPerMinute;
	}
	
	double TimeController::GetTempoSwell() const
	{
		return beatsPerMinute / SecondsPerMinute;
	}
	
	double TimeController::GetNoteSeconds( TimeController::NoteLengthType noteLengthType ) const
	{
		double multiple = 4;
		double fraction = beatFraction;
		while ( fraction != 1 )
		{
			multiple /= 2; 
			fraction /= 2;
		}
		double seconds;
		switch ( noteLengthType ) 
		{
		case WholeNote:
			seconds = 4.0 * multiple * GetSecondsPerBeat();
			break;

		case HalfNote:
			seconds = 2.0 * multiple * GetSecondsPerBeat();
			break;

		case QuarterNote:
			seconds = multiple * GetSecondsPerBeat();
			break;
				
		case EighthNote:
			seconds = ( 1.0 / 2.0 ) * multiple * GetSecondsPerBeat();
			break;
						
		case SixteenthNote:
			seconds = ( 1.0 / 4.0 ) * multiple * GetSecondsPerBeat();
			break;
		
		case ThirtySecondNote:
			seconds = ( 1.0 / 8.0 ) * multiple * GetSecondsPerBeat();
			break;		

		case WholeNoteDotted:
			seconds = ( 3.0 / 2.0 ) * 4.0 * multiple * GetSecondsPerBeat();
			break;
			
		case HalfNoteDotted:
			seconds = ( 3.0 / 2.0 ) * 2.0 * multiple * GetSecondsPerBeat();		
			break;
			
		case QuarterNoteDotted:
			seconds = ( 3.0 / 2.0 ) * multiple * GetSecondsPerBeat();
			break;
			
		case EighthNoteDotted:
			seconds = ( 3.0 / 2.0 ) * ( 1.0 / 2.0 ) * multiple * GetSecondsPerBeat();
			break;
				
		case SixteenthNoteDotted:
			seconds = ( 3.0 / 2.0 ) * ( 1.0 / 4.0 ) * multiple * GetSecondsPerBeat();
			break;

		case ThirtySecondNoteDotted:
			seconds = ( 3.0 / 2.0 ) * ( 1.0 / 8.0 ) * multiple * GetSecondsPerBeat();
			break;
			

		case WholeNoteTriplet:
			seconds = ( 1.0 / 3.0 ) * 4.0 * multiple * GetSecondsPerBeat();
			break;
			
		case HalfNoteTriplet:
			seconds = ( 1.0 / 3.0 ) * 2.0 * multiple * GetSecondsPerBeat();		
			break;	
				
		case QuarterNoteTriplet:
			seconds = ( 1.0 / 3.0 ) * multiple * GetSecondsPerBeat();
			break;

		case EighthNoteTriplet:
			seconds = ( 1.0 / 3.0 ) * ( 1.0 / 2.0 ) * multiple * GetSecondsPerBeat();
			break;
							
		case SixteenthNoteTriplet:
			seconds = ( 1.0 / 3.0 ) * ( 1.0 / 4.0 ) * multiple * GetSecondsPerBeat();
			break;
					
		case ThirtySecondNoteTriplet:
			seconds = ( 1.0 / 3.0 ) * ( 1.0 / 8.0 ) * multiple * GetSecondsPerBeat();
			break;			

		default:
			return -1;
		}

		return seconds;

	}
	
	double TimeController::GetNoteSeconds( TimeController::NoteLengthType type, int beatCount ) const
	{
		return GetNoteSeconds( type ) / static_cast<double>( beatCount );
	}

	double TimeController::GetNoteSwell( TimeController::NoteLengthType noteLengthType ) const
	{
		double multiple = 4;
		double fraction = beatFraction;
		while ( fraction != 1 )
		{
			multiple /= 2; 
			fraction /= 2;
		}
		switch ( noteLengthType ) 
		{
		case WholeNote:
			return ( 1.0 / 4.0 ) * multiple * GetSecondsPerBeat();

		case HalfNote:
			return ( 1.0 / 2.0 ) * multiple * GetSecondsPerBeat();
		
		case QuarterNote:
			return multiple * GetSecondsPerBeat();
		
		case EighthNote:
			return 2.0 * multiple * GetSecondsPerBeat();
		
		case SixteenthNote:
			return 4.0 * multiple * GetSecondsPerBeat();
		
		case ThirtySecondNote:
			return 8.0 * multiple * GetSecondsPerBeat();

		case WholeNoteDotted:
			return ( 2.0 / 3.0 ) * ( 1.0 / 4.0 ) * multiple * GetSecondsPerBeat();

		case HalfNoteDotted:
			return ( 2.0 / 3.0 ) * ( 1.0 / 2.0 ) * multiple * GetSecondsPerBeat();		

		case QuarterNoteDotted:
			return ( 2.0 / 3.0 ) * multiple * GetSecondsPerBeat();
		
		case EighthNoteDotted:
			return ( 2.0 / 3.0 ) * 2.0 * multiple * GetSecondsPerBeat();
	
		case SixteenthNoteDotted:
			return ( 2.0 / 3.0 ) * 4.0 * multiple * GetSecondsPerBeat();

		case ThirtySecondNoteDotted:
			return ( 2.0 / 3.0 ) * 8.0 * multiple * GetSecondsPerBeat();


		case WholeNoteTriplet:
			return 3.0 * ( 1.0 / 4.0 ) * multiple * GetSecondsPerBeat();

		case HalfNoteTriplet:
			return 3.0 * ( 1.0 / 2.0 ) * multiple * GetSecondsPerBeat();		
		
		case QuarterNoteTriplet:
			return 3.0 * multiple * GetSecondsPerBeat();
					
		case EighthNoteTriplet:
			return 3.0 * 2.0 * multiple * GetSecondsPerBeat();
					
		case SixteenthNoteTriplet:
			return 3.0 * 4.0 * multiple * GetSecondsPerBeat();
		
		case ThirtySecondNoteTriplet:
			return 3.0 * 8.0 * multiple * GetSecondsPerBeat();
			
		default:
			return -1;
		}
	}
}
